#include "SyntaxAnalysis.hpp"

/* <程序> -> <分程序> EOF */
void SyntaxAnalysis::parseProgram()
{
    /* main process */
    ProcessStack.push(Process("main"));

    parseSubProgram();
    saveProcess("main");

    ProcessStack.pop();

    if (!matchTerminal(EOF_TYPE))
        errorOutput("文件结尾符号缺失", "EOF");
}

/* <分程序> -> begin <说明语句表> ; <执行语句表> end */
void SyntaxAnalysis::parseSubProgram()
{
    if (!matchTerminal(BEGIN_TYPE))
    {
        errorOutput("<分程序> 缺失关键字", "`begin`");
        /* <说明语句表> */
        if (!searchTerminal(INTEGER_TYPE))
            throw std::invalid_argument("重大语法错误");
    }

    /* <说明语句表> ; */
    parseDeclarationStatementList();

    parseExecutionStatementList();

    if (!matchTerminal(END_TYPE))
    {
        errorOutput("<分程序> 关键字不匹配", "begin-end");
        throw std::invalid_argument("重大语法错误");
    }
}

/* <说明语句表> -> <说明语句> { ; <说明语句> }
 * - 修改为：<说明语句表> ; -> { <说明语句> ; }
 * - 错误情况：INTEGER_TYPE -> IDENTIFIER_TYPE
 */
void SyntaxAnalysis::parseDeclarationStatementList()
{
    while (searchTerminal(INTEGER_TYPE) ||
           searchTerminal(IDENTIFIER_TYPE, IDENTIFIER_TYPE) ||
           searchTerminal(IDENTIFIER_TYPE, FUNCTION_TYPE))
    {
        parseDeclarationStatement();

        if (!matchTerminal(SEMICOLON_TYPE))
        {
            if (searchTerminal(END_TYPE))
                errorOutput("<执行语句表> 缺失", "");
            else
                errorOutput("<说明语句> 后缺失分号", "`;`");
            return;
        }
    }
}

/* <说明语句> -> <变量说明> │ <函数说明>
 * 判断 <说明语句> :
 * - 类型说明开头 INTEGER_TYPE
 * - 错误情况：INTEGER_TYPE -> IDENTIFIER_TYPE
 */
void SyntaxAnalysis::parseDeclarationStatement()
{
    if (searchTerminal(0, FUNCTION_TYPE))
        parseFunctionDeclaration();
    else
        parseVariableDeclaration();
}

/* <变量说明> -> integer <变量>
 * - 默认类型：INTEGER_TYPE or IDENTIFIER_TYPE, IDENTIFIER_TYPE
 * - 特殊错误：<函数说明> 关键字 `function` 错误
 * - 变量名称：1.不能与当前过程重名  2.不能与当前过程中的变量重名
 */
void SyntaxAnalysis::parseVariableDeclaration()
{
    if (!matchTerminal(INTEGER_TYPE))
    {
        errorOutput("<变量说明> 类型声明错误", currentToken->first);
        skipErrors();
        return;
    }

    auto variablePair = std::make_pair(currentToken->first, ProcessStack.top().pName);
    if (variablePair.first == variablePair.second)
    {
        errorOutput("<变量> 与当前过程重名", variablePair.first + " - " + variablePair.second);
        skipErrors();
        return;
    }

    if (!matchTerminal(IDENTIFIER_TYPE))
    {
        errorOutput("<变量> 类型错误", currentToken->first);
        throw std::invalid_argument("重大语法错误");
    }

    /* <函数说明> 关键字 `function` 错误 -> integer <标识符> <标识符> `(` */
    if (searchTerminal(IDENTIFIER_TYPE, LEFT_PAREN_TYPE))
    {
        errorOutput("<函数说明> 关键字`function`错误", variablePair.first);
        throw std::invalid_argument("重大语法错误");
    }

    auto it = VariablesTable.find(variablePair);
    if (it != VariablesTable.end())
    {
        errorOutput("<变量> 重定义", variablePair.first);
        skipErrors();
        return;
    }
    else
        VariablesTable.insert(variablePair);

    saveVariable(variablePair);
}

/* <变量> -> <标识符>
 * - 类型：IDENTIFIER_TYPE
 * - 在变量表VariablesTable or 当前函数返回值（F := xxx）
 */
bool SyntaxAnalysis::parseVariable()
{
    auto variablePair = std::make_pair(currentToken->first, ProcessStack.top().pName);

    if (!matchTerminal(IDENTIFIER_TYPE))
    {
        errorOutput("<变量> 类型错误", variablePair.first);
        return false;
    }

    /* is current ProcessName? */
    if (variablePair.first == variablePair.second)
        return true;

    /* is in VariablesTable? */
    auto it = VariablesTable.find(variablePair);
    if (it == VariablesTable.end())
    {
        errorOutput("<变量> 未定义", variablePair.first);
        return false;
    }

    return true;
}

/* <函数说明> -> integer function <标识符> ( <变量说明> ) ; <函数体>
 * 默认类型：INTEGER_TYPE / IDENTIFIER_TYPE, FUNCTION_TYPE
 */
void SyntaxAnalysis::parseFunctionDeclaration()
{
    if (!matchTerminal(INTEGER_TYPE))
    {
        errorOutput("<函数说明> 类型声明错误", currentToken->first);
        matchTerminal(0);
    }

    if (!matchTerminal(FUNCTION_TYPE))
    {
        errorOutput("<函数说明> 缺少函数声明", "`function`");
        throw std::invalid_argument("重大语法错误");
    }

    /* save Process */
    std::string processName = currentToken->first;
    if (!matchTerminal(IDENTIFIER_TYPE))
    {
        errorOutput("<函数说明> 过程名类型错误",  currentToken->first);
        throw std::invalid_argument("重大语法错误");
    }

    /* 不同层级过程名不可以相同 */
    auto it = ProcessesTable.find(processName);
    if (it != ProcessesTable.end())
        errorOutput("过程重定义 ", processName);
    else
        ProcessesTable.insert(processName);

    if (!matchTerminal(LEFT_PAREN_TYPE))
    {
        errorOutput("<函数声明> 符号缺少", "`(`");
        if (!searchTerminal(INTEGER_TYPE))
            throw std::invalid_argument("重大语法错误");
    }

    /* 函数参数属于过程 */
    ProcessStack.push(Process(processName));
    parseVariableDeclaration();

    if (!matchTerminal(RIGHT_PAREN_TYPE))
    {
        errorOutput("<函数声明> 符号不匹配", "`(` - `)`");
        if (!searchTerminal(SEMICOLON_TYPE))
            throw std::invalid_argument("重大语法错误");
    }

    if (!matchTerminal(SEMICOLON_TYPE))
    {
        errorOutput("<函数说明> 符号缺少", "`;`");
        if (!searchTerminal(BEGIN_TYPE))
            throw std::invalid_argument("重大语法错误");
    }

    /* 进入过程 */
    parseFunctionBody();

    saveProcess(processName);
    ProcessStack.pop();
}

/* <参数> -> <变量> */
void SyntaxAnalysis::parseParameter()
{
    parseVariable();
}

/* <函数体> -> begin <说明语句表> ; <执行语句表> end */
void SyntaxAnalysis::parseFunctionBody()
{
    if (!matchTerminal(BEGIN_TYPE))
    {
        errorOutput("<函数体> 缺失关键字", "`begin`");
        /* <说明语句表> */
        if (!searchTerminal(INTEGER_TYPE))
            throw std::invalid_argument("重大语法错误");
    }

    /* <说明语句表> ; */
    parseDeclarationStatementList();

    parseExecutionStatementList();

    if (!matchTerminal(END_TYPE))
    {
        errorOutput("<函数体> 关键字不匹配", "begin-end");
        throw std::invalid_argument("重大语法错误");
    }
}

/* <执行语句表> -> <执行语句> { ; <执行语句> } */
void SyntaxAnalysis::parseExecutionStatementList()
{
    parseExecutionStatement();

    while (matchTerminal(SEMICOLON_TYPE))
        parseExecutionStatement();
}

/* <执行语句> -> <读语句> │ <写语句> │ <赋值语句> │ <条件语句>
 * 错误情况：
 * - 关键字错误：IF_TYPE / READ_TYPE / WRITE_TYPE -> IDENTIFIER_TYPE
 * - <说明语句>
 * - `;` 多余：<执行语句表> `;` end
 */
void SyntaxAnalysis::parseExecutionStatement()
{
    if (searchTerminal(IF_TYPE))
        parseConditionalStatement();
    else if (searchTerminal(READ_TYPE))
        parseReadStatement();
    else if (searchTerminal(WRITE_TYPE))
        parseWriteStatement();
    else if (searchTerminal(IDENTIFIER_TYPE, ASSIGN_TYPE))
        parseAssignmentStatement();
    /* 关键字错误：IF_TYPE / READ_TYPE / WRITE_TYPE -> IDENTIFIER_TYPE */
    else if (searchTerminal(IDENTIFIER_TYPE))
    {
        errorOutput("<执行语句> 关键词错误",  currentToken->first);
        skipErrors();
    }
    /* <说明语句> */
    else if (searchTerminal(INTEGER_TYPE))
    {
        errorOutput("<说明语句表> 与 <执行语句表> 位置错误", "");
        parseDeclarationStatement();
    }
    /* <执行语句表> ; end */
    else if (searchTerminal(END_TYPE))
        errorOutput("<执行语句表> 后多余符号", "`;`");
    else
    {
        errorOutput("<执行语句> 未知格式错误 ", currentToken->first);
        skipErrors();
    }
}

/* <读语句> -> read ( <变量> ) */
void SyntaxAnalysis::parseReadStatement()
{
    if (!matchTerminal(READ_TYPE))
    {
        errorOutput("<读语句> 关键字缺失", "`read`");
        skipErrors();
        return;
    }

    if (!matchTerminal(LEFT_PAREN_TYPE))
    {
        errorOutput("<读语句> 关键字缺失", "`(`");
        if (!searchTerminal(IDENTIFIER_TYPE))
        {
            skipErrors();
            return;
        }
    }

    parseVariable();

    if (!matchTerminal(RIGHT_PAREN_TYPE))
    {
        errorOutput("<读语句> 关键字不匹配", "`(` - `)`");
        skipErrors();
    }
}

/* <写语句> -> write ( <变量> ) */
void SyntaxAnalysis::parseWriteStatement()
{
    if (!matchTerminal(WRITE_TYPE))
    {
        errorOutput("<写语句> 关键字缺失", "`write`");
        skipErrors();
        return;
    }

    if (!matchTerminal(LEFT_PAREN_TYPE))
    {
        errorOutput("<写语句> 关键字缺失", "`(`");
        if (!searchTerminal(IDENTIFIER_TYPE))
        {
            skipErrors();
            return;
        }
    }

    parseVariable();

    if (!matchTerminal(RIGHT_PAREN_TYPE))
    {
        errorOutput("<写语句> 关键字不匹配", "`(` - `)`");
        skipErrors();
    }
}

/* <赋值语句> -> <变量> := <算术表达式> */
void SyntaxAnalysis::parseAssignmentStatement()
{
    if (!parseVariable())
    {
        skipErrors();
        return;
    }

    if (!matchTerminal(ASSIGN_TYPE))
    {
        std::string symbol = currentToken->first;
        if (matchTerminal(EQUAL_TYPE, MULTIPLY_TYPE))
            errorOutput("<赋值语句> 符号使用错误", symbol);
        else
        {
            errorOutput("<赋值语句> 缺失赋值符号", "`:=`");
            skipErrors();
            return;
        }
    }

    parseArithmeticExpression();
}

/* <算术表达式> -> <项> { - <项> } */
void SyntaxAnalysis::parseArithmeticExpression()
{
    parseTerm();

    while (matchTerminal(MINUS_TYPE))
        parseTerm();
}

/* <项> -> <因子> { * <因子> } */
void SyntaxAnalysis::parseTerm()
{
    parseFactor();

    while (matchTerminal(MULTIPLY_TYPE))
        parseFactor();
}

/* <因子> -> <变量> │ <常数> │ <函数调用> */
void SyntaxAnalysis::parseFactor()
{
    /* <变量> or <函数调用> */
    if (searchTerminal(IDENTIFIER_TYPE))
    {
        if (searchTerminal(IDENTIFIER_TYPE, LEFT_PAREN_TYPE))
            parseFunctionCall();
        else
            parseVariable();
    }
    else if (!matchTerminal(CONSTANT_TYPE))
    {
        errorOutput("<因子> 类型错误",  currentToken->first);
    }
}

/* <函数调用> -> <标识符> ( <算术表达式> )*/
void SyntaxAnalysis::parseFunctionCall()
{
    std::string functionName = currentToken->first;

    if (!matchTerminal(IDENTIFIER_TYPE))
    {
        errorOutput("<函数调用> 类型错误", currentToken->first);
        return;
    }

    auto it = ProcessesTable.find(functionName);
    if (it == ProcessesTable.end())
    {
        errorOutput("函数未定义", functionName);
    }

    if (!matchTerminal(LEFT_PAREN_TYPE))
    {
        errorOutput("<函数调用> 关键字缺失", "`(`");
        matchTerminal(0);
    }

    parseArithmeticExpression();

    if (!matchTerminal(RIGHT_PAREN_TYPE))
    {
        errorOutput("<函数调用> 关键字不匹配", "`(` - `)`");
    }
}

/* <条件语句> -> if <条件表达式> then <执行语句> else <执行语句> */
void SyntaxAnalysis::parseConditionalStatement()
{
    if (!matchTerminal(IF_TYPE))
    {
        errorOutput("<条件语句> 缺失关键字", "if");
        skipErrors();
        return;
    }

    parseConditionalExpression();

    if (!matchTerminal(THEN_TYPE))
    {
        errorOutput("<条件语句> 缺失关键字", "`then`");
        skipErrors();
        return;
    }

    parseExecutionStatement();

    if (!matchTerminal(ELSE_TYPE))
    {
        errorOutput("<条件语句> 缺失关键字", "`else`");
        skipErrors();
        return;
    }

    parseExecutionStatement();
}

/* <条件表达式> -> <算术表达式> <关系运算符> <算术表达式> */
void SyntaxAnalysis::parseConditionalExpression()
{
    parseArithmeticExpression();

    if (!matchTerminal(EQUAL_TYPE, GREATER_THAN_TYPE))
    {
        errorOutput("<条件表达式> 缺失关系运算符", "");
    }

    parseArithmeticExpression();
}